"""
实体提取器 - 从简历中提取结构化实体信息
支持人员、公司、技能、教育经历等实体类型
"""

import asyncio
import re
import json
from typing import Dict, Any, List, Optional, Tuple
from datetime import datetime
import spacy
from openai import AsyncOpenAI

from ...core.interfaces import Entity, Relationship
from ...core.events import EventEmitter
from ...core.config import config


class EntityExtractor(EventEmitter):
    """实体提取器 - 使用LLM和NLP模型提取实体"""
    
    def __init__(self):
        super().__init__()
        self.client = None
        self.nlp = None
        self._initialized = False
    
    async def initialize(self):
        """初始化NLP模型和LLM客户端"""
        if self._initialized:
            return
        
        try:
            # 初始化OpenAI客户端
            api_key = config.get("external_services.openai.api_key")
            if api_key:
                self.client = AsyncOpenAI(api_key=api_key)
            
            # 初始化spaCy模型
            try:
                self.nlp = spacy.load("zh_core_web_sm")
            except OSError:
                try:
                    self.nlp = spacy.load("en_core_web_sm")
                except OSError:
                    print("Warning: No spaCy model found. Some NLP features will be limited.")
                    self.nlp = None
            
            self._initialized = True
            
            await self.emit("entity_extractor_initialized", {
                "llm_available": self.client is not None,
                "nlp_available": self.nlp is not None
            })
            
        except Exception as e:
            await self.emit_error("entity_extractor_initialization", e)
            raise
    
    async def extract_entities(self, content: str, metadata: Dict[str, Any]) -> Tuple[List[Entity], List[Relationship]]:
        """从内容中提取实体和关系"""
        if not self._initialized:
            await self.initialize()
        
        try:
            # 并行执行不同的提取方法
            tasks = [
                self._extract_with_llm(content),
                self._extract_with_rules(content),
            ]
            
            if self.nlp:
                tasks.append(self._extract_with_nlp(content))
            
            results = await asyncio.gather(*tasks, return_exceptions=True)
            
            # 合并结果
            all_entities = []
            all_relationships = []
            
            for result in results:
                if isinstance(result, Exception):
                    continue
                
                entities, relationships = result
                all_entities.extend(entities)
                all_relationships.extend(relationships)
            
            # 去重和清理
            unique_entities = self._deduplicate_entities(all_entities)
            unique_relationships = self._deduplicate_relationships(all_relationships)
            
            await self.emit("entities_extracted", {
                "entities_count": len(unique_entities),
                "relationships_count": len(unique_relationships),
                "content_length": len(content)
            })
            
            return unique_entities, unique_relationships
            
        except Exception as e:
            await self.emit_error("extract_entities", e)
            return [], []
    
    async def _extract_with_llm(self, content: str) -> Tuple[List[Entity], List[Relationship]]:
        """使用LLM提取实体"""
        if not self.client:
            return [], []
        
        try:
            prompt = f"""
请从以下简历内容中提取结构化信息，返回JSON格式：

简历内容：
{content[:3000]}  # 限制长度避免token超限

请提取以下信息：
1. 个人信息（姓名、联系方式、位置等）
2. 工作经历（公司、职位、时间、职责）
3. 教育经历（学校、专业、学位、时间）
4. 技能（技术技能、语言技能等）
5. 项目经历
6. 证书和荣誉

返回格式：
{{
  "person": {{
    "name": "姓名",
    "email": "邮箱",
    "phone": "电话",
    "location": "地址"
  }},
  "experiences": [
    {{
      "company": "公司名",
      "position": "职位",
      "start_date": "开始时间",
      "end_date": "结束时间",
      "description": "工作描述"
    }}
  ],
  "education": [
    {{
      "school": "学校名",
      "degree": "学位",
      "major": "专业",
      "start_date": "开始时间",
      "end_date": "结束时间"
    }}
  ],
  "skills": ["技能1", "技能2"],
  "projects": [
    {{
      "name": "项目名",
      "description": "项目描述",
      "technologies": ["技术1", "技术2"]
    }}
  ]
}}
"""
            
            response = await self.client.chat.completions.create(
                model="gpt-3.5-turbo",
                messages=[
                    {"role": "system", "content": "你是一个专业的简历分析专家，擅长从简历中提取结构化信息。"},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.1
            )
            
            # 解析LLM响应
            response_text = response.choices[0].message.content
            structured_data = json.loads(response_text)
            
            # 转换为实体和关系
            entities, relationships = self._convert_llm_result_to_entities(structured_data)
            
            return entities, relationships
            
        except Exception as e:
            await self.emit_error("llm_extraction", e)
            return [], []
    
    def _convert_llm_result_to_entities(self, data: Dict[str, Any]) -> Tuple[List[Entity], List[Relationship]]:
        """将LLM结果转换为实体和关系"""
        entities = []
        relationships = []
        
        # 生成唯一ID
        def generate_id(prefix: str, name: str) -> str:
            return f"{prefix}_{re.sub(r'[^a-zA-Z0-9_]', '_', name.lower())}"
        
        # 个人实体
        person_data = data.get("person", {})
        if person_data.get("name"):
            person_id = generate_id("person", person_data["name"])
            person_entity = Entity(
                id=person_id,
                type="Person",
                properties={
                    "name": person_data.get("name", ""),
                    "email": person_data.get("email", ""),
                    "phone": person_data.get("phone", ""),
                    "location": person_data.get("location", ""),
                    "created_at": datetime.now().isoformat()
                }
            )
            entities.append(person_entity)
            
            # 工作经历
            for exp in data.get("experiences", []):
                if exp.get("company"):
                    company_id = generate_id("company", exp["company"])
                    company_entity = Entity(
                        id=company_id,
                        type="Company",
                        properties={
                            "name": exp["company"],
                            "created_at": datetime.now().isoformat()
                        }
                    )
                    entities.append(company_entity)
                    
                    # 职位实体
                    if exp.get("position"):
                        position_id = generate_id("position", f"{exp['company']}_{exp['position']}")
                        position_entity = Entity(
                            id=position_id,
                            type="Position",
                            properties={
                                "title": exp["position"],
                                "company": exp["company"],
                                "start_date": exp.get("start_date", ""),
                                "end_date": exp.get("end_date", ""),
                                "description": exp.get("description", ""),
                                "created_at": datetime.now().isoformat()
                            }
                        )
                        entities.append(position_entity)
                        
                        # 关系：人员-工作于-公司
                        work_relationship = Relationship(
                            source=person_id,
                            target=company_id,
                            type="WORKED_AT",
                            properties={
                                "position": exp["position"],
                                "start_date": exp.get("start_date", ""),
                                "end_date": exp.get("end_date", ""),
                                "created_at": datetime.now().isoformat()
                            }
                        )
                        relationships.append(work_relationship)
                        
                        # 关系：人员-担任-职位
                        position_relationship = Relationship(
                            source=person_id,
                            target=position_id,
                            type="HELD_POSITION",
                            properties={
                                "start_date": exp.get("start_date", ""),
                                "end_date": exp.get("end_date", ""),
                                "created_at": datetime.now().isoformat()
                            }
                        )
                        relationships.append(position_relationship)
            
            # 教育经历
            for edu in data.get("education", []):
                if edu.get("school"):
                    school_id = generate_id("school", edu["school"])
                    school_entity = Entity(
                        id=school_id,
                        type="School",
                        properties={
                            "name": edu["school"],
                            "created_at": datetime.now().isoformat()
                        }
                    )
                    entities.append(school_entity)
                    
                    # 关系：人员-就读于-学校
                    edu_relationship = Relationship(
                        source=person_id,
                        target=school_id,
                        type="STUDIED_AT",
                        properties={
                            "degree": edu.get("degree", ""),
                            "major": edu.get("major", ""),
                            "start_date": edu.get("start_date", ""),
                            "end_date": edu.get("end_date", ""),
                            "created_at": datetime.now().isoformat()
                        }
                    )
                    relationships.append(edu_relationship)
            
            # 技能
            for skill_name in data.get("skills", []):
                skill_id = generate_id("skill", skill_name)
                skill_entity = Entity(
                    id=skill_id,
                    type="Skill",
                    properties={
                        "name": skill_name,
                        "created_at": datetime.now().isoformat()
                    }
                )
                entities.append(skill_entity)
                
                # 关系：人员-掌握-技能
                skill_relationship = Relationship(
                    source=person_id,
                    target=skill_id,
                    type="HAS_SKILL",
                    properties={
                        "created_at": datetime.now().isoformat()
                    }
                )
                relationships.append(skill_relationship)
            
            # 项目经历
            for project in data.get("projects", []):
                if project.get("name"):
                    project_id = generate_id("project", project["name"])
                    project_entity = Entity(
                        id=project_id,
                        type="Project",
                        properties={
                            "name": project["name"],
                            "description": project.get("description", ""),
                            "technologies": project.get("technologies", []),
                            "created_at": datetime.now().isoformat()
                        }
                    )
                    entities.append(project_entity)
                    
                    # 关系：人员-参与-项目
                    project_relationship = Relationship(
                        source=person_id,
                        target=project_id,
                        type="WORKED_ON",
                        properties={
                            "created_at": datetime.now().isoformat()
                        }
                    )
                    relationships.append(project_relationship)
        
        return entities, relationships
    
    async def _extract_with_rules(self, content: str) -> Tuple[List[Entity], List[Relationship]]:
        """使用规则方法提取实体"""
        entities = []
        relationships = []
        
        try:
            # 邮箱提取
            email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
            emails = re.findall(email_pattern, content)
            
            # 电话提取
            phone_pattern = r'1[3-9]\d{9}|(?:\+86[-\s]?)?(?:\d{3,4}[-\s]?)?\d{7,8}'
            phones = re.findall(phone_pattern, content)
            
            # 技能关键词提取
            tech_skills = [
                'Python', 'Java', 'JavaScript', 'C++', 'C#', 'Go', 'Rust',
                'React', 'Vue', 'Angular', 'Node.js', 'Django', 'Flask',
                'MySQL', 'PostgreSQL', 'MongoDB', 'Redis',
                'Docker', 'Kubernetes', 'Git', 'Linux',
                'Machine Learning', 'Deep Learning', 'AI', 'NLP'
            ]
            
            found_skills = []
            content_upper = content.upper()
            for skill in tech_skills:
                if skill.upper() in content_upper:
                    found_skills.append(skill)
            
            # 公司名称提取（基于常见后缀）
            company_suffixes = ['有限公司', '股份有限公司', '科技有限公司', 'Inc.', 'Ltd.', 'Corp.', 'LLC']
            company_pattern = r'[\u4e00-\u9fa5A-Za-z\s]+(?:' + '|'.join(re.escape(suffix) for suffix in company_suffixes) + ')'
            companies = re.findall(company_pattern, content)
            
            # 创建实体（简单版本，实际应用中需要更复杂的逻辑）
            for i, email in enumerate(emails):
                entity = Entity(
                    id=f"email_{i}",
                    type="Email",
                    properties={"value": email}
                )
                entities.append(entity)
            
            for i, phone in enumerate(phones):
                entity = Entity(
                    id=f"phone_{i}",
                    type="Phone", 
                    properties={"value": phone}
                )
                entities.append(entity)
            
            for i, skill in enumerate(found_skills):
                entity = Entity(
                    id=f"skill_rule_{i}",
                    type="Skill",
                    properties={"name": skill, "extraction_method": "rule_based"}
                )
                entities.append(entity)
            
            return entities, relationships
            
        except Exception as e:
            await self.emit_error("rule_extraction", e)
            return [], []
    
    async def _extract_with_nlp(self, content: str) -> Tuple[List[Entity], List[Relationship]]:
        """使用NLP模型提取实体"""
        if not self.nlp:
            return [], []
        
        try:
            entities = []
            relationships = []
            
            # 使用spaCy进行命名实体识别
            doc = self.nlp(content[:1000000])  # 限制长度
            
            for ent in doc.ents:
                entity = Entity(
                    id=f"nlp_{ent.label_}_{len(entities)}",
                    type=self._map_spacy_label(ent.label_),
                    properties={
                        "text": ent.text,
                        "label": ent.label_,
                        "start": ent.start_char,
                        "end": ent.end_char,
                        "extraction_method": "nlp"
                    }
                )
                entities.append(entity)
            
            return entities, relationships
            
        except Exception as e:
            await self.emit_error("nlp_extraction", e)
            return [], []
    
    def _map_spacy_label(self, spacy_label: str) -> str:
        """映射spaCy标签到我们的实体类型"""
        mapping = {
            "PERSON": "Person",
            "ORG": "Organization", 
            "GPE": "Location",
            "MONEY": "Money",
            "DATE": "Date",
            "TIME": "Time"
        }
        return mapping.get(spacy_label, "Entity")
    
    def _deduplicate_entities(self, entities: List[Entity]) -> List[Entity]:
        """实体去重"""
        seen = set()
        unique_entities = []
        
        for entity in entities:
            # 基于类型和主要属性创建唯一键
            key_props = []
            if entity.type == "Person" and "name" in entity.properties:
                key_props.append(entity.properties["name"])
            elif entity.type == "Company" and "name" in entity.properties:
                key_props.append(entity.properties["name"])
            elif entity.type == "Skill" and "name" in entity.properties:
                key_props.append(entity.properties["name"])
            
            key = (entity.type, tuple(key_props))
            if key not in seen:
                seen.add(key)
                unique_entities.append(entity)
        
        return unique_entities
    
    def _deduplicate_relationships(self, relationships: List[Relationship]) -> List[Relationship]:
        """关系去重"""
        seen = set()
        unique_relationships = []
        
        for rel in relationships:
            key = (rel.source, rel.target, rel.type)
            if key not in seen:
                seen.add(key)
                unique_relationships.append(rel)
        
        return unique_relationships